package com.xinqi.modules.course.clazz.service.impl;

import com.xinqi.common.base.response.R;
import com.xinqi.common.base.user.Account;
import com.xinqi.common.core.constant.ChatRemindConstants;
import com.xinqi.common.core.enums.ChatRemindTypeEnum;
import com.xinqi.common.core.enums.ClassRoleEnum;
import com.xinqi.common.core.utils.PlaceholderUtils;
import com.xinqi.common.core.utils.StringUtils;
import com.xinqi.modules.chat.chat.official.client.ChatRemindContentClient;
import com.xinqi.modules.chat.chat.official.dto.req.ChatRemindContentBatchCreateDTO;
import com.xinqi.modules.chat.chat.official.dto.req.ChatRemindContentCreateDTO;
import com.xinqi.modules.course.clazz.domain.ClassGroupStudentEntity;
import com.xinqi.modules.course.clazz.domain.ClassStudentEntity;
import com.xinqi.modules.course.clazz.dto.rsp.ClassGroupResultDTO;
import com.xinqi.modules.course.clazz.dto.rsp.ClassGroupStudentResultDTO;
import com.xinqi.modules.course.clazz.dto.rsp.ClassResultDTO;
import com.xinqi.modules.course.clazz.dto.rsp.ClassStudentResultDTO;
import com.xinqi.modules.course.clazz.service.*;
import com.xinqi.modules.course.comment.domain.CommentEntity;
import com.xinqi.modules.course.content.domain.CourseContentEntity;
import com.xinqi.modules.course.content.service.CourseContentService;
import com.xinqi.modules.prepare.prepare.client.PreparePrepareClient;
import com.xinqi.modules.prepare.prepare.dto.rsp.PrepareResultDTO;
import lombok.RequiredArgsConstructor;
import org.apache.commons.collections4.CollectionUtils;
import org.springframework.scheduling.annotation.Async;
import org.springframework.stereotype.Service;

import java.util.*;
import java.util.stream.Collectors;

/**
 * 新奇提醒服务接口
 * <p>
 * 新奇提醒 -- 采用同步进行，发送消息
 * 1.量小 ：基本基于被操作人、老师、助教一类进行消息发送
 * 2.数据不存在 ：涉及移出删除一类，数据删除后无法获取数据
 * <p>
 * 但是：
 * 小组管理中学生发起自由分组/老师发起随机分组会通知班级内所有学生，
 * 班级学生上限目前为300人，而融云一对多同时发送不同消息时有限制，
 * 故此处消息发送耗时长，采用异步发送进行通知
 * <p>
 *
 * @Author：yyzhen
 * @Package：com.xinqi.modules.course.clazz.service.impl
 * @Project：XingqiClass-Cloud-Plus
 * @name：ChatRemindSyncServiceImpl
 * @Date：2023/5/11 15:26
 * @Filename：ChatRemindSyncServiceImpl
 */

@Service("chatRemindSyncService")
@RequiredArgsConstructor
public class ChatRemindSyncServiceImpl implements ChatRemindSyncService {

    private final ClassService classService;

    private final ClassStudentService classStudentService;

    private final ClassGroupService classGroupService;

    private final ClassGroupStudentService classGroupStudentService;

    private final CourseContentService courseContentService;

    private final PreparePrepareClient preparePrepareClient;

    private final ChatRemindContentClient remindContentClient;

    /**
     * 新奇提醒机器人 -- 评论
     *
     * @param user   操作人
     * @param entity 评论实体
     */

    @Async("threadPoolTaskExecutor")
    @Override
    public void commentChatRemind(Account user, CommentEntity entity) {
        if (Objects.isNull(entity)) {
            return;
        }
        CourseContentEntity courseContent = courseContentService.selectByContentIdAndType(entity.getContentId(), entity.getType());
        if (Objects.isNull(courseContent)) {
            return;
        }
        Long userId = Objects.isNull(courseContent.getUserId()) ? courseContent.getCreateBy() : courseContent.getUserId();
        if (Objects.equals(user.getId(), userId)) {
            return;
        }
        ClassResultDTO classResult = classService.findByClassId(entity.getClassId());
        if (Objects.isNull(classResult)) {
            return;
        }
        //评论内容分为图片和文字
        String title = "";
        if (StringUtils.isNotEmpty(entity.getTitle())) {
            title = title + entity.getTitle();
        }
        if (StringUtils.isNotEmpty(entity.getImageList()) || StringUtils.isNotEmpty(entity.getImages())) {
            title = title + "[图片]";
        }

        // 获取用户班级信息
        ClassStudentResultDTO student = classStudentService.findByStudentId(entity.getClassId(), user.getId());

        Map<String, Object> params = new HashMap<>();
        if (Objects.nonNull(student)) {
            params.put("userName", student.getStudentName() + student.getRelationship());
        } else {
            params.put("userName", user.getNickname());
        }
        params.put("courseName", classResult.getCourseName());
        params.put("className", classResult.getName());
        params.put("courseTitle", courseContent.getTitle());
        params.put("title", title);
        entity.setUserId(userId);

        this.commentInitChatRemind(ChatRemindConstants.REMIND_COMMENT_TEMPLATE, params, entity, ChatRemindTypeEnum.COMMENT);
    }

    /**
     * 新奇提醒机器人 -- 回复
     *
     * @param user   操作人
     * @param entity 被回复实体
     */

    @Async("threadPoolTaskExecutor")
    @Override
    public void replyChatRemind(Account user, CommentEntity entity) {
        if (Objects.isNull(entity)) {
            return;
        }
        CourseContentEntity courseContent = courseContentService.selectByContentIdAndType(entity.getContentId(), entity.getType());
        if (Objects.isNull(courseContent)) {
            return;
        }
        if (Objects.equals(user.getId(), entity.getUserId())) {
            return;
        }
        ClassResultDTO classResult = classService.findByClassId(entity.getClassId());
        if (Objects.isNull(classResult)) {
            return;
        }
        //评论内容分为图片和文字
        String title = "";
        if (StringUtils.isNotEmpty(entity.getTitle())) {
            title = title + entity.getTitle();
        }
        if (StringUtils.isNotEmpty(entity.getImageList()) || StringUtils.isNotEmpty(entity.getImages())) {
            title = title + "[图片]";
        }

        // 获取用户班级信息
        ClassStudentResultDTO student = classStudentService.findByStudentId(entity.getClassId(), user.getId());

        Map<String, Object> params = new HashMap<>();
        if (Objects.nonNull(student)) {
            params.put("userName", student.getStudentName() + student.getRelationship());
        } else {
            params.put("userName", user.getNickname());
        }
        params.put("courseName", classResult.getCourseName());
        params.put("className", classResult.getName());
        params.put("courseTitle", courseContent.getTitle());
        params.put("title", title);

        this.commentInitChatRemind(ChatRemindConstants.REMIND_REPLY_TEMPLATE, params, entity, ChatRemindTypeEnum.REPLY);
    }

    /**
     * 新奇提醒机器人 -- 点赞
     *
     * @param user   操作人
     * @param entity 被点赞实体
     */

    @Async("threadPoolTaskExecutor")
    @Override
    public void giveChatRemind(Account user, CommentEntity entity) {
        if (Objects.isNull(entity)) {
            return;
        }
        CourseContentEntity courseContent = courseContentService.selectByContentIdAndType(entity.getContentId(), entity.getType());
        if (Objects.isNull(courseContent)) {
            return;
        }
        if (Objects.equals(user.getId(), entity.getUserId())) {
            return;
        }
        ClassResultDTO classResult = classService.findByClassId(entity.getClassId());
        if (Objects.isNull(classResult)) {
            return;
        }
        //评论内容分为图片和文字
        String title = StringUtils.isEmpty(entity.getTitle()) ? "[图片]" : entity.getTitle();

        Map<String, Object> params = new HashMap<>();
        params.put("courseName", classResult.getCourseName());
        params.put("className", classResult.getName());
        params.put("courseTitle", courseContent.getTitle());
        params.put("title", title);

        this.commentInitChatRemind(ChatRemindConstants.REMIND_GIVE_TEMPLATE, params, entity, ChatRemindTypeEnum.GIVE);
    }


    /**
     * 新奇提醒机器人 -- 被邀请加入备课区
     *
     * @param operationUser 操作人
     * @param prepareId     备课区ID
     * @param userId        被邀请用户ID
     */

    @Async("threadPoolTaskExecutor")
    @Override
    public void joinPrepare(String operationUser, Long prepareId, Long userId) {
        PrepareResultDTO prepare = R.as(preparePrepareClient.findById(prepareId));
        if (Objects.isNull(prepare)) {
            return;
        }
        Map<String, Object> params = new HashMap<>();
        params.put("operationUser", operationUser);
        params.put("prepareName", prepare.getName());
        String content = PlaceholderUtils.replaceWithMap(ChatRemindConstants.REMIND_JOIN_PREPARE_TEMPLATE, params);
        remindContentClient.insert(new ChatRemindContentCreateDTO(userId, ChatRemindTypeEnum.JOIN_CLASS, content));
    }

    /**
     * 新奇提醒机器人 -- 你被移出备课区通知
     *
     * @param operationUser 操作人
     * @param prepareId     备课区ID
     * @param userId        被移除用户ID
     */
    @Async("threadPoolTaskExecutor")
    @Override
    public void dropPrepare(String operationUser, Long prepareId, Long userId) {
        PrepareResultDTO prepare = R.as(preparePrepareClient.findById(prepareId));
        if (Objects.isNull(prepare)) {
            return;
        }
        Map<String, Object> params = new HashMap<>();
        params.put("operationUser", operationUser);
        params.put("prepareName", prepare.getName());
        String content = PlaceholderUtils.replaceWithMap(ChatRemindConstants.REMIND_DROP_PREPARE_MEMBER_TEMPLATE, params);
        remindContentClient.insert(new ChatRemindContentCreateDTO(userId, ChatRemindTypeEnum.DROP_CLASS, content));
    }

    /**
     * 新奇提醒机器人 -- 你被移出备课区通知 -- 批量
     *
     * @param operationUser 操作人
     * @param prepareId     备课区ID
     * @param userIds       被移除用户ID
     */

    @Async("threadPoolTaskExecutor")
    @Override
    public void batchDropPrepare(String operationUser, Long prepareId, List<Long> userIds) {
        PrepareResultDTO prepare = R.as(preparePrepareClient.findById(prepareId));
        if (Objects.isNull(prepare)) {
            return;
        }
        Map<String, Object> params = new HashMap<>();
        params.put("operationUser", operationUser);
        params.put("prepareName", prepare.getName());
        String content = PlaceholderUtils.replaceWithMap(ChatRemindConstants.REMIND_DROP_PREPARE_MEMBER_TEMPLATE, params);
        List<ChatRemindContentCreateDTO> remindList = new ArrayList<>();
        userIds.forEach(userId -> {
            remindList.add(new ChatRemindContentCreateDTO(userId, ChatRemindTypeEnum.DROP_CLASS, content));
        });
        if (CollectionUtils.isNotEmpty(remindList)) {
            remindContentClient.batchInsert(new ChatRemindContentBatchCreateDTO(remindList));
        }
    }

    /**
     * 新奇提醒机器人 -- 主动退出备课区
     *
     * @param operationUser 操作人
     * @param prepareId     备课区ID
     */

    @Async("threadPoolTaskExecutor")
    @Override
    public void quitPrepare(String operationUser, Long prepareId) {
        PrepareResultDTO prepare = R.as(preparePrepareClient.findById(prepareId));
        if (Objects.isNull(prepare)) {
            return;
        }
        Map<String, Object> params = new HashMap<>();
        params.put("userName", operationUser);
        params.put("prepareName", prepare.getName());
        String content = PlaceholderUtils.replaceWithMap(ChatRemindConstants.REMIND_DROP_PREPARE_TEMPLATE, params);
        remindContentClient.insert(new ChatRemindContentCreateDTO(prepare.getUserId(), ChatRemindTypeEnum.DROP_CLASS, content));
    }


    /**
     * 新奇提醒机器人 -- 成员入课 -- 审核
     *
     * @param classId    班级ID
     * @param courseName 课程名称
     * @param className  班级名称
     */

    @Async("threadPoolTaskExecutor")
    @Override
    public void applyClass(Long classId, String courseName, String className) {
        List<ChatRemindContentCreateDTO> remindList = new ArrayList<>();
        Map<String, Object> params = new HashMap<>();
        params.put("courseName", courseName);
        params.put("className", className);
        String content = PlaceholderUtils.replaceWithMap(ChatRemindConstants.REMIND_APPLY_JOIN_CLASS_TEMPLATE, params);
        //新奇提醒机器人 -- 成员入课 -- 助教
        List<ClassStudentResultDTO> assistant = classStudentService.findByClassRole(classId, ClassRoleEnum.ASSISTANT.getCode());
        assistant.forEach(item -> {
            remindList.add(new ChatRemindContentCreateDTO(item.getStudentId(), classId, ChatRemindTypeEnum.JOIN_CLASS, content));
        });
        //新奇提醒机器人 -- 成员入课 -- 老师
        List<ClassStudentResultDTO> teacher = classStudentService.findByClassRole(classId, ClassRoleEnum.TEACHER.getCode());
        teacher.forEach(item -> remindList.add(new ChatRemindContentCreateDTO(item.getStudentId(), classId, ChatRemindTypeEnum.JOIN_CLASS, content)));
        if (CollectionUtils.isNotEmpty(remindList)) {
            remindContentClient.batchInsert(new ChatRemindContentBatchCreateDTO(remindList));
        }
    }

    /**
     * 审核拒绝
     *
     * @param classId    班级id
     * @param relationId 关系学生的id
     * @param courseName 课程id
     * @param className  班级名称
     */
    @Async("threadPoolTaskExecutor")
    @Override
    public void teacherReject(Long classId, Long relationId, String courseName, String className) {
        List<ChatRemindContentCreateDTO> remindList = new ArrayList<>();
        Map<String, Object> params = new HashMap<>();
        params.put("courseName", courseName);
        params.put("className", className);
        String content = PlaceholderUtils.replaceWithMap(ChatRemindConstants.REMIND_REJECT_JOIN_CLASS_TEMPLATE, params);
        //新奇提醒机器人 -- 审核拒绝 -- 学生
        remindList.add(new ChatRemindContentCreateDTO(relationId, classId, ChatRemindTypeEnum.AUDIT_REJECT, content));
        if (CollectionUtils.isNotEmpty(remindList)) {
            remindContentClient.batchInsert(new ChatRemindContentBatchCreateDTO(remindList));
        }
    }

    /**
     * 新奇提醒机器人 -- 关系用户加入班级
     *
     * @param classId    班级ID
     * @param relationId 加入学生ID，可以是
     * @param type       审核方式
     */

    @Async("threadPoolTaskExecutor")
    @Override
    public void studentJoinClass(Long classId, Long relationId, ChatRemindTypeEnum type) {
        ClassResultDTO classResult = classService.findByClassId(classId);
        if (Objects.isNull(classResult)) {
            return;
        }
        ClassStudentResultDTO student = classStudentService.findByStudentId(classId, relationId);
        if (Objects.isNull(student)) {
            return;
        }
        Map<String, Object> params = new HashMap<>();
        params.put("userName", student.getNickName());
        params.put("courseName", classResult.getCourseName());
        params.put("className", classResult.getName());
        String content = PlaceholderUtils.replaceWithMap(ChatRemindConstants.REMIND_JOIN_CLASS_TEMPLATE, params);

        this.classChatRemind(classId, classResult.getCourseId(), content, type);
    }

    /**
     * 新奇提醒机器人 -- 审核通过，通知关系用户
     *
     * @param classId    班级ID
     * @param relationId 加入学生ID，可以是
     * @param type       审核方式
     */

    @Async("threadPoolTaskExecutor")
    @Override
    public void acceptPass(Long classId, Long relationId, ChatRemindTypeEnum type) {
        ClassResultDTO classResult = classService.findByClassId(classId);
        if (Objects.isNull(classResult)) {
            return;
        }

        Map<String, Object> params = new HashMap<>();
        params.put("courseName", classResult.getCourseName());
        params.put("courseId", classResult.getCourseId());
        params.put("className", classResult.getName());
        String content = PlaceholderUtils.replaceWithMap(ChatRemindConstants.REMIND_JOIN_CLASS_TEMPLATE, params);

        this.classChatRemindToRelation(classResult.getCourseId(), classId, relationId, content, type);
    }

    /**
     * 新奇提醒机器人 -- 成员退出班级
     *
     * @param classId   班级ID
     * @param studentId 退出学生ID
     */

    @Override
    public void studentQuitClass(Long classId, Long studentId, String studentName, Account user) {
        ClassResultDTO classResult = classService.findByClassId(classId);
        if (Objects.isNull(classResult)) {
            return;
        }

        Map<String, Object> params = new HashMap<>();
        params.put("courseName", classResult.getCourseName());
        params.put("className", classResult.getName());
        params.put("userName", studentName);
        String content = PlaceholderUtils.replaceWithMap(ChatRemindConstants.REMIND_DROP_CLASS_TEMPLATE, params);

        this.classChatRemind(classResult.getCourseId(), classId, content, ChatRemindTypeEnum.DROP_CLASS);

        //你被移出班级通知 -- 非学生主动退出
        if (!Objects.equals(studentId, user.getId())) {
            Map<String, Object> params2 = new HashMap<>();
            params2.put("operationUser", user.getNickname());
            params2.put("courseName", classResult.getCourseName());
            params2.put("className", classResult.getName());
            String studentContent = PlaceholderUtils.replaceWithMap(ChatRemindConstants.REMIND_DROP_CLASS_STUDENT_TEMPLATE, params2);
            remindContentClient.insert(new ChatRemindContentCreateDTO(studentId, classId, ChatRemindTypeEnum.DROP_CLASS, studentContent));
        }

    }

    /**
     * 新奇提醒机器人 -- 小组变动 -- 发起自由分组
     *
     * @param classId       : 班级ID
     * @param groupName     : 自由分组名称
     * @param operationUser 操作人名称
     * @return : void
     * @Title:
     * @MethodName: joinFreeGroup
     * @Exception
     * @Description:
     * @author: yyzhen
     * @date: 2023/5/12 10:26
     */

    @Async("threadPoolTaskExecutor")
    @Override
    public void freeGroup(Long classId, String groupName, String operationUser) {
        ClassResultDTO classResult = classService.findByClassId(classId);
        if (Objects.isNull(classResult)) {
            return;
        }
        List<ChatRemindContentCreateDTO> remindList = new ArrayList<>();
        Map<String, Object> params = new HashMap<>();
        params.put("operationUser", operationUser);
        params.put("courseName", classResult.getCourseName());
        params.put("className", classResult.getName());
        params.put("groupName", groupName);
        String content = PlaceholderUtils.replaceWithMap(ChatRemindConstants.REMIND_LAUNCH_FREE_GROUP_TEMPLATE, params);
        List<ClassStudentResultDTO> studentList = classStudentService.findClassRelationStudentByClassId(classId);
        studentList.forEach(student -> remindList.add(new ChatRemindContentCreateDTO(student.getStudentId(), classId, ChatRemindTypeEnum.GROUP_CHANGE, content)));
        if (CollectionUtils.isNotEmpty(remindList)) {
            remindContentClient.batchInsert(new ChatRemindContentBatchCreateDTO(remindList));
        }
    }

    /**
     * 新奇提醒机器人 -- 小组变动 -- 随机分组
     *
     * @param classId   班级ID
     * @param groupName 主分组名称
     * @param sonIdList 子小组ID集合
     * @return : void
     * @Title:
     * @MethodName: joinRandomGroup
     * @Exception
     * @Description:
     * @author: yyzhen
     * @date: 2023/5/12 10:43
     */

    @Async("threadPoolTaskExecutor")
    @Override
    public void randomGroup(Long classId, String groupName, List<Long> sonIdList) {
        ClassResultDTO classResult = classService.findByClassId(classId);
        if (Objects.isNull(classResult)) {
            return;
        }

        List<ClassGroupStudentResultDTO> classGroupStudentList = classGroupStudentService.findStudentListByGroupIds(sonIdList);

        Map<Long, List<ClassStudentEntity>> relationStudentMap = this.changeRelationStudent(classId, classGroupStudentList);

        List<ChatRemindContentCreateDTO> remindList = this.initRemindList(classResult, groupName, classGroupStudentList, relationStudentMap);

        if (CollectionUtils.isNotEmpty(remindList)) {
            remindContentClient.batchInsert(new ChatRemindContentBatchCreateDTO(remindList));
        }
    }

    private List<ChatRemindContentCreateDTO> initRemindList(ClassResultDTO classResult, String groupName, List<ClassGroupStudentResultDTO> classGroupStudentList, Map<Long, List<ClassStudentEntity>> relationStudentMap) {
        List<ChatRemindContentCreateDTO> remindList = new ArrayList<>();

        classGroupStudentList.forEach(l -> {
            if (relationStudentMap.containsKey(l.getStudentId())) {
                List<ClassStudentEntity> existList = relationStudentMap.get(l.getStudentId());
                for (ClassStudentEntity classStudent : existList) {
                    Map<String, Object> params = new HashMap<>();
                    params.put("courseName", classResult.getCourseName());
                    params.put("className", classResult.getName());
                    params.put("groupName1", groupName);
                    params.put("groupName2", l.getJoinedName());
                    String content = PlaceholderUtils.replaceWithMap(ChatRemindConstants.REMIND_SYSTEM_RANDOM_GROUP_TEMPLATE, params);
                    remindList.add(new ChatRemindContentCreateDTO(classStudent.getStudentId(), classResult.getId(), ChatRemindTypeEnum.GROUP_CHANGE, content));
                }
            }
        });

        return remindList;
    }

    private Map<Long, List<ClassStudentEntity>> changeRelationStudent(Long classId, List<ClassGroupStudentResultDTO> classGroupStudentList) {
        Map<Long, List<ClassStudentEntity>> studentMap = new HashMap<>();
        List<Long> masterStudentIdList = classGroupStudentList.stream().map(ClassGroupStudentResultDTO::getStudentId).collect(Collectors.toList());
        List<ClassStudentEntity> relationStudentEntityList = classStudentService.findRelationStudentListByClassIdAndMasterIdList(classId, masterStudentIdList);

        if (CollectionUtils.isNotEmpty(relationStudentEntityList)) {
            for (ClassStudentEntity classStudentEntity : relationStudentEntityList) {
                if (studentMap.containsKey(classStudentEntity.getStudentId())) {
                    List<ClassStudentEntity> existList = studentMap.get(classStudentEntity.getStudentId());
                    existList.add(classStudentEntity);
                } else {
                    List<ClassStudentEntity> existList = new ArrayList<>();
                    existList.add(classStudentEntity);
                    studentMap.put(classStudentEntity.getStudentId(), existList);
                }
            }
        }

        return studentMap;
    }

    /**
     * 新奇机器人 -- 小组变动 -- 被移入小组通知
     *
     * @param operationUser 操作人名称
     * @param studentId     学生ID
     * @param group         移入小组
     * @return : void
     * @Title:
     * @MethodName: studentJoinGroup
     * @Exception
     * @Description:
     * @author: yyzhen
     * @date: 2023/5/12 10:57
     */

    @Async("threadPoolTaskExecutor")
    @Override
    public void studentJoinGroup(String operationUser, Long studentId, ClassGroupResultDTO group) {
        ClassResultDTO classResult = classService.findByClassId(group.getClassId());
        if (Objects.isNull(classResult)) {
            return;
        }
        ClassGroupResultDTO group1 = classGroupService.findById(group.getPid());
        remindContentClient.insert(this.groupChatRemind(ChatRemindConstants.REMIND_MOVE_IN_GROUP_TEMPLATE, operationUser, studentId, classResult, group1, group));
    }


    /**
     * 新奇机器人 -- 小组变动 -- 被移出小组通知
     *
     * @param operationUser 操作人名称
     * @param studentId     学生ID
     * @param group         移除小组
     * @return : void
     * @Title:
     * @MethodName: studentDropGroup
     * @Exception
     * @Description:
     * @author: yyzhen
     * @date: 2023/5/12 10:57
     */

    @Async("threadPoolTaskExecutor")
    @Override
    public void studentDropGroup(String operationUser, Long studentId, ClassGroupResultDTO group) {
        ClassResultDTO classResult = classService.findByClassId(group.getClassId());
        if (Objects.isNull(classResult)) {
            return;
        }
        ClassGroupResultDTO group1 = classGroupService.findById(group.getPid());
        remindContentClient.insert(this.groupChatRemind(ChatRemindConstants.REMIND_MOVE_OUT_GROUP_TEMPLATE, operationUser, studentId, classResult, group1, group));
    }

    /**
     * 新奇机器人 -- 小组变动 -- 退出班级小组通知
     *
     * @param operationUser 操作人名称
     * @param studentId     学生ID
     * @param group         退出小组
     * @return : void
     * @Title:
     * @MethodName: studentQuitGroup
     * @Exception
     * @Description:
     * @author: yyzhen
     * @date: 2023/5/12 10:57
     */

    @Async("threadPoolTaskExecutor")
    @Override
    public void studentQuitGroup(String operationUser, Long studentId, ClassGroupResultDTO group) {
        ClassResultDTO classResult = classService.findByClassId(group.getClassId());
        if (Objects.isNull(classResult)) {
            return;
        }
        ClassGroupResultDTO group1 = classGroupService.findById(group.getPid());
        List<ChatRemindContentCreateDTO> remindList = new ArrayList<>();
        this.groupChatRemind(operationUser, classResult, group1, group, remindList);
        if (CollectionUtils.isNotEmpty(remindList)) {
            remindContentClient.batchInsert(new ChatRemindContentBatchCreateDTO(remindList));
        }
    }


    /**
     * 新奇机器人 -- 小组变动 -- 被设为小组组长
     *
     * @param operationUser 操作人名称
     * @param studentId     学生ID
     * @param group         设置小组
     * @return : void
     * @Title:
     * @MethodName: studentSetGroupTeamLeader
     * @Exception
     * @Description:
     * @author: yyzhen
     * @date: 2023/5/12 11:52
     */

    @Async("threadPoolTaskExecutor")
    @Override
    public void studentSetGroupTeamLeader(String operationUser, Long studentId, ClassGroupResultDTO group) {
        ClassResultDTO classResult = classService.findByClassId(group.getClassId());
        if (Objects.isNull(classResult)) {
            return;
        }
        ClassGroupResultDTO group1 = classGroupService.findById(group.getPid());
        remindContentClient.insert(this.groupChatRemind(ChatRemindConstants.REMIND_SET_GROUP_LEADER_TEMPLATE, operationUser, studentId, classResult, group1, group));
    }

    /**
     * 新奇机器人 -- 小组变动 -- 更换小组
     *
     * @param operationUser 操作人名称
     * @param group         更换后小组
     * @param entityList    更换学生
     * @return : void
     * @Title:
     * @MethodName: studentBatchChangeGroup
     * @Exception
     * @Description:
     * @author: yyzhen
     * @date: 2023/5/12 11:53
     */

    @Async("threadPoolTaskExecutor")
    @Override
    public void studentBatchChangeGroup(String operationUser, ClassGroupResultDTO group, List<ClassStudentEntity> entityList) {
        if (CollectionUtils.isEmpty(entityList)) {
            return;
        }
        ClassResultDTO classResult = classService.findByClassId(group.getClassId());
        if (Objects.isNull(classResult)) {
            return;
        }
        ClassGroupResultDTO group1 = classGroupService.findById(group.getPid());
        List<ChatRemindContentCreateDTO> remindList = new ArrayList<>();
        entityList.forEach(item -> remindList.add(this.groupChatRemind(ChatRemindConstants.REMIND_MOVE_IN_GROUP_TEMPLATE, operationUser, item.getStudentId(), classResult, group1, group)));
        if (CollectionUtils.isNotEmpty(remindList)) {
            remindContentClient.batchInsert(new ChatRemindContentBatchCreateDTO(remindList));
        }
    }


    /**
     * 新奇机器人 -- 小组变动 -- 被移入小组通知
     *
     * @param operationUser 操作人名称
     * @param entityList    移入学生
     * @return : void
     * @Title:
     * @MethodName: studentBatchJoinGroup
     * @Exception
     * @Description:
     * @author: yyzhen
     * @date: 2023/5/12 11:53
     */

    @Async("threadPoolTaskExecutor")
    @Override
    public void studentBatchJoinGroup(String operationUser, List<ClassGroupStudentEntity> entityList) {
        if (CollectionUtils.isEmpty(entityList)) {
            return;
        }
        List<ChatRemindContentCreateDTO> remindList = new ArrayList<>();
        Map<Long, ClassResultDTO> classMap = new HashMap<>();
        Map<Long, ClassGroupResultDTO> groupMap = new HashMap<>();

        this.initClassAndGroup(classMap, groupMap, entityList);
        entityList.forEach(item -> {
            ClassGroupResultDTO group2 = groupMap.get(item.getGroupId());
            if (Objects.isNull(group2)) {
                return;
            }
            ClassGroupResultDTO group1 = groupMap.get(group2.getPid());
            ClassResultDTO classResult = classMap.get(group2.getClassId());
            remindList.add(this.groupChatRemind(ChatRemindConstants.REMIND_MOVE_IN_GROUP_TEMPLATE, operationUser, item.getStudentId(), classResult, group1, group2));
        });
        if (CollectionUtils.isNotEmpty(remindList)) {
            remindContentClient.batchInsert(new ChatRemindContentBatchCreateDTO(remindList));
        }
    }


    /**
     * 新奇机器人 -- 小组变动 -- 被移出小组通知
     *
     * @param entityList 移出学生
     * @return : void
     * @Title:
     * @MethodName: studentBatchDropGroup
     * @Exception
     * @Description:
     * @author: yyzhen
     * @date: 2023/5/12 11:54
     */

    @Async("threadPoolTaskExecutor")
    @Override
    public void studentBatchDropGroup(List<ClassGroupStudentEntity> entityList, Account user) {
        if (CollectionUtils.isEmpty(entityList)) {
            return;
        }
        List<ChatRemindContentCreateDTO> remindList = new ArrayList<>();
        Map<Long, ClassResultDTO> classMap = new HashMap<>();
        Map<Long, ClassGroupResultDTO> groupMap = new HashMap<>();

        this.initClassAndGroup(classMap, groupMap, entityList);
        entityList.forEach(item -> {
            ClassGroupResultDTO group2 = groupMap.get(item.getGroupId());
            if (Objects.isNull(group2)) {
                return;
            }
            ClassGroupResultDTO group1 = groupMap.get(group2.getPid());
            ClassResultDTO classResult = classMap.get(group2.getClassId());
            if (Objects.equals(user.getId(), item.getStudentId())) {
                //退出班级小组通知
                this.groupChatRemind(user.getNickname(), classResult, group1, group2, remindList);
            } else {
                //被移出小组通知
                remindList.add(this.groupChatRemind(ChatRemindConstants.REMIND_MOVE_OUT_GROUP_TEMPLATE, user.getNickname(), item.getStudentId(), classResult, group1, group2));
            }

        });
        if (CollectionUtils.isNotEmpty(remindList)) {
            remindContentClient.batchInsert(new ChatRemindContentBatchCreateDTO(remindList));
        }
    }

    /**
     * 新奇机器人 -- 身份变更 -- 学生变课代表
     *
     * @param classId   : 班级ID
     * @param studentId : 学生ID
     * @return : void
     * @Title:
     * @MethodName: studentChangeRepresentative
     * @Exception
     * @Description:
     * @author: yyzhen
     * @date: 2023/5/12 15:13
     */

    @Async("threadPoolTaskExecutor")
    @Override
    public void studentChangeRepresentative(Long classId, Long studentId, Account user) {
        ClassResultDTO classResult = classService.findByClassId(classId);
        if (Objects.isNull(classResult)) {
            return;
        }
        ClassStudentResultDTO student = classStudentService.findByStudentId(classId, studentId);
        if (Objects.isNull(student)) {
            return;
        }
        ClassStudentResultDTO mainStudent = classStudentService.findByStudentId(classId, student.getPatStuRefId());
        if (Objects.isNull(mainStudent)) {
            return;
        }

        Map<String, Object> studentParams = new HashMap<>();
        studentParams.put("operationUser", user.getNickname());
        studentParams.put("courseName", classResult.getCourseName());
        studentParams.put("className", classResult.getName());
        String studentContent = PlaceholderUtils.replaceWithMap(ChatRemindConstants.REMIND_SET_REPRESENTATIVE_TEMPLATE_2, studentParams);
        Map<String, Object> teacherParams = new HashMap<>();
        teacherParams.put("userName", mainStudent.getStudentName());
        teacherParams.put("courseName", classResult.getCourseName());
        teacherParams.put("className", classResult.getName());
        String teacherContent = PlaceholderUtils.replaceWithMap(ChatRemindConstants.REMIND_SET_REPRESENTATIVE_TEMPLATE_1, teacherParams);
        //新奇提醒机器人 -- 身份变更
        this.sendIdentityChatRemind(classId, studentId, studentContent, teacherContent);
    }

    /**
     * 新奇机器人 -- 身份变更 -- 课代表变学生
     *
     * @param classId   : 班级ID
     * @param studentId : 学生ID
     * @return : void
     * @Title:
     * @MethodName: representativeChangeStudent
     * @Exception
     * @Description:
     * @author: yyzhen
     * @date: 2023/5/12 15:13
     */

    @Async("threadPoolTaskExecutor")
    @Override
    public void representativeChangeStudent(Long classId, Long studentId, Account user) {
        ClassResultDTO classResult = classService.findByClassId(classId);
        if (Objects.isNull(classResult)) {
            return;
        }
        ClassStudentResultDTO student = classStudentService.findByStudentId(classId, studentId);
        if (Objects.isNull(student)) {
            return;
        }
        Map<String, Object> studentParams = new HashMap<>();
        studentParams.put("operationUser", user.getNickname());
        studentParams.put("courseName", classResult.getCourseName());
        studentParams.put("className", classResult.getName());
        String studentContent = PlaceholderUtils.replaceWithMap(ChatRemindConstants.REMIND_REMOVE_REPRESENTATIVE_TEMPLATE_2, studentParams);
        Map<String, Object> teacherParams = new HashMap<>();
        teacherParams.put("userName", student.getNickName());
        teacherParams.put("courseName", classResult.getCourseName());
        teacherParams.put("className", classResult.getName());
        String teacherContent = PlaceholderUtils.replaceWithMap(ChatRemindConstants.REMIND_REMOVE_REPRESENTATIVE_TEMPLATE_1, teacherParams);
        //新奇提醒机器人 -- 身份变更
        this.sendIdentityChatRemind(classId, studentId, studentContent, teacherContent);

    }


    /**
     * 新奇机器人 -- 身份变更 -- 学生变助教
     *
     * @param classId   : 班级ID
     * @param studentId : 学生ID
     * @return : void
     * @Title:
     * @MethodName: studentChangeAssistant
     * @Exception
     * @Description:
     * @author: yyzhen
     * @date: 2023/5/12 15:13
     */

    @Async("threadPoolTaskExecutor")
    @Override
    public void studentChangeAssistant(Long classId, Long studentId, Account user) {
        ClassResultDTO classResult = classService.findByClassId(classId);
        if (Objects.isNull(classResult)) {
            return;
        }
        Map<String, Object> params = new HashMap<>();
        params.put("operationUser", user.getNickname());
        params.put("courseName", classResult.getCourseName());
        params.put("className", classResult.getName());
        String content = PlaceholderUtils.replaceWithMap(ChatRemindConstants.REMIND_SET_ASSISTANT_TEMPLATE, params);
        //新奇提醒机器人 -- 身份变更
        remindContentClient.insert(new ChatRemindContentCreateDTO(studentId, classId, ChatRemindTypeEnum.IDENTITY_CHANGE, content));
    }

    /**
     * 新奇机器人 -- 身份变更 -- 助教变学生
     *
     * @param classId   : 班级ID
     * @param studentId : 学生ID
     * @return : void
     * @Title:
     * @MethodName: assistantChangeStudent
     * @Exception
     * @Description:
     * @author: yyzhen
     * @date: 2023/5/12 15:13
     */

    @Async("threadPoolTaskExecutor")
    @Override
    public void assistantChangeStudent(Long classId, Long studentId, Account user) {
        ClassResultDTO classResult = classService.findByClassId(classId);
        if (Objects.isNull(classResult)) {
            return;
        }
        Map<String, Object> params = new HashMap<>();
        params.put("operationUser", user.getNickname());
        params.put("courseName", classResult.getCourseName());
        params.put("className", classResult.getName());
        String content = PlaceholderUtils.replaceWithMap(ChatRemindConstants.REMIND_REMOVE_ASSISTANT_TEMPLATE, params);
        //新奇提醒机器人 -- 身份变更
        remindContentClient.insert(new ChatRemindContentCreateDTO(studentId, classId, ChatRemindTypeEnum.IDENTITY_CHANGE, content));
    }


    /**
     * 新奇机器人 -- 身份变更 -- 课代表变助教
     *
     * @param classId   : 班级ID
     * @param studentId : 学生ID
     * @return : void
     * @Title:
     * @MethodName: representativeChangeAssistant
     * @Exception
     * @Description:
     * @author: yyzhen
     * @date: 2023/5/12 15:13
     */

    @Async("threadPoolTaskExecutor")
    @Override
    public void representativeChangeAssistant(Long classId, Long studentId, Account user) {
        ClassResultDTO classResult = classService.findByClassId(classId);
        if (Objects.isNull(classResult)) {
            return;
        }
        Map<String, Object> params = new HashMap<>();
        params.put("operationUser", user.getNickname());
        params.put("courseName", classResult.getCourseName());
        params.put("className", classResult.getName());
        String content = PlaceholderUtils.replaceWithMap(ChatRemindConstants.REMIND_SET_ASSISTANT_TEMPLATE, params);
        //新奇提醒机器人 -- 身份变更
        remindContentClient.insert(new ChatRemindContentCreateDTO(studentId, classId, ChatRemindTypeEnum.IDENTITY_CHANGE, content));
    }

    /**
     * 新奇机器人 -- 身份变更 -- 助教变课代表
     *
     * @param classId   : 班级ID
     * @param studentId : 学生ID
     * @return : void
     * @Title:
     * @MethodName: assistantChangeRepresentative
     * @Exception
     * @Description:
     * @author: yyzhen
     * @date: 2023/5/12 15:13
     */

    @Async("threadPoolTaskExecutor")
    @Override
    public void assistantChangeRepresentative(Long classId, Long studentId, Account user) {
        ClassResultDTO classResult = classService.findByClassId(classId);
        if (Objects.isNull(classResult)) {
            return;
        }
        ClassStudentResultDTO student = classStudentService.findByStudentId(classId, studentId);
        if (Objects.isNull(student)) {
            return;
        }
        Map<String, Object> studentParams = new HashMap<>();
        studentParams.put("operationUser", user.getNickname());
        studentParams.put("courseName", classResult.getCourseName());
        studentParams.put("className", classResult.getName());
        String studentContent = PlaceholderUtils.replaceWithMap(ChatRemindConstants.REMIND_SET_REPRESENTATIVE_TEMPLATE_2, studentParams);
        Map<String, Object> teacherParams = new HashMap<>();
        teacherParams.put("userName", student.getNickName());
        teacherParams.put("courseName", classResult.getCourseName());
        teacherParams.put("className", classResult.getName());
        String teacherContent = PlaceholderUtils.replaceWithMap(ChatRemindConstants.REMIND_SET_REPRESENTATIVE_TEMPLATE_1, teacherParams);
        //新奇提醒机器人 -- 身份变更
        this.sendIdentityChatRemind(classId, studentId, studentContent, teacherContent);
    }


    /**
     * 评论点赞回复公共封装
     *
     * @param template
     * @param params
     * @param entity
     * @param type
     * @return
     */

    private void commentInitChatRemind(String template, Map<String, Object> params,
                                       CommentEntity entity, ChatRemindTypeEnum type) {
        String content = PlaceholderUtils.replaceWithMap(template, params);

        ChatRemindContentCreateDTO remindContent = new ChatRemindContentCreateDTO();
        remindContent.setUserId(entity.getUserId());
        remindContent.setType(type);
        remindContent.setContentType(entity.getType());
        remindContent.setContentId(entity.getContentId());
        remindContent.setTimes(entity.getTimes());
        remindContent.setClassId(entity.getClassId());
        remindContent.setContent(content);

        remindContentClient.insert(remindContent);
    }

    /**
     * 加入班级、退出班级公共封装,免审核入课不需要给关系用户发消息
     *
     * @param classId
     * @param content
     */

    private void classChatRemind(Long courseId, Long classId, String content, ChatRemindTypeEnum type) {
        List<ChatRemindContentCreateDTO> remindList = new ArrayList<>();
        //新奇提醒机器人 -- 成员退课 -- 老师
        List<ClassStudentResultDTO> teacher = classStudentService.findByClassRole(classId, ClassRoleEnum.TEACHER.getCode());
        teacher.forEach(item -> remindList.add(new ChatRemindContentCreateDTO(item.getStudentId(), courseId, classId, type, content)));

        //新奇提醒机器人 -- 成员退课 -- 助教
        List<ClassStudentResultDTO> assistant = classStudentService.findByClassRole(classId, ClassRoleEnum.ASSISTANT.getCode());
        assistant.forEach(item -> remindList.add(new ChatRemindContentCreateDTO(item.getStudentId(), courseId, classId, type, content)));

        if (CollectionUtils.isNotEmpty(remindList)) {
            remindContentClient.batchInsert(new ChatRemindContentBatchCreateDTO(remindList));
        }
    }

    /**
     * 给关系用户发消息
     *
     * @param classId
     * @param relationId
     * @param content
     * @param type
     */
    private void classChatRemindToRelation(Long courseId, Long classId, Long relationId, String content, ChatRemindTypeEnum type) {
        List<ChatRemindContentCreateDTO> remindList = new ArrayList<>();
        //新奇提醒机器人 -- 成员入课 -- 关系用户
        remindList.add(new ChatRemindContentCreateDTO(relationId, courseId, classId, type, content));
        if (CollectionUtils.isNotEmpty(remindList)) {
            remindContentClient.batchInsert(new ChatRemindContentBatchCreateDTO(remindList));
        }
    }

    /**
     * 小组变动封装
     *
     * @param template
     * @param operationUser
     * @param studentId
     * @param classResult
     * @param group1
     * @param group2
     * @return
     */

    private ChatRemindContentCreateDTO groupChatRemind(String template, String operationUser, Long studentId, ClassResultDTO classResult, ClassGroupResultDTO group1, ClassGroupResultDTO group2) {
        Map<String, Object> params = new HashMap<>();
        params.put("operationUser", operationUser);
        params.put("courseName", Objects.isNull(classResult) ? "" : classResult.getCourseName());
        params.put("className", Objects.isNull(classResult) ? "" : classResult.getName());
        params.put("groupName1", Objects.isNull(group1) ? "" : group1.getName());
        params.put("groupName2", Objects.isNull(group2) ? "" : group2.getName());
        String content = PlaceholderUtils.replaceWithMap(template, params);

        return new ChatRemindContentCreateDTO(studentId, group2.getClassId(), ChatRemindTypeEnum.GROUP_CHANGE, content);
    }

    /**
     * 小组变动封装
     *
     * @param userName
     * @param classResult
     * @param group1
     * @param group2
     * @param remindList
     */

    private void groupChatRemind(String userName, ClassResultDTO classResult, ClassGroupResultDTO group1, ClassGroupResultDTO group2, List<ChatRemindContentCreateDTO> remindList) {
        Map<String, Object> params = new HashMap<>();
        params.put("userName", userName);
        params.put("courseName", Objects.isNull(classResult) ? "" : classResult.getCourseName());
        params.put("className", Objects.isNull(classResult) ? "" : classResult.getName());
        params.put("groupName1", Objects.isNull(group1) ? "" : group1.getName());
        params.put("groupName2", Objects.isNull(group2) ? "" : group2.getName());
        String content = PlaceholderUtils.replaceWithMap(ChatRemindConstants.REMIND_DROP_CLASS_GROUP_TEMPLATE, params);

        //新奇提醒机器人 -- 小组变动 -- 助教
        List<ClassStudentResultDTO> assistant = classStudentService.findByClassRole(group2.getClassId(), ClassRoleEnum.ASSISTANT.getCode());
        assistant.forEach(item -> {
            remindList.add(new ChatRemindContentCreateDTO(item.getStudentId(), group2.getClassId(), ChatRemindTypeEnum.GROUP_CHANGE, content));
        });
        //新奇提醒机器人 -- 小组变动 -- 老师
        List<ClassStudentResultDTO> teacher = classStudentService.findByClassRole(group2.getClassId(), ClassRoleEnum.TEACHER.getCode());
        teacher.forEach(item -> {
            remindList.add(new ChatRemindContentCreateDTO(item.getStudentId(), group2.getClassId(), ChatRemindTypeEnum.GROUP_CHANGE, content));
        });
    }

    /**
     * 根据小组ID集合获取班级及分组map
     *
     * @param classMap
     * @param groupMap
     * @param entityList
     */

    private void initClassAndGroup(Map<Long, ClassResultDTO> classMap, Map<Long, ClassGroupResultDTO> groupMap, List<ClassGroupStudentEntity> entityList) {
        entityList.forEach(entity -> {
            ClassGroupResultDTO group1 = null;
            ClassGroupResultDTO group2 = null;
            ClassResultDTO classResult = null;
            if (groupMap.containsKey(entity.getGroupId())) {
                group2 = groupMap.get(entity.getGroupId());
            } else {
                group2 = classGroupService.findById(entity.getGroupId());
                if (Objects.nonNull(group2)) {
                    groupMap.put(group2.getId(), group2);
                }
            }
            if (Objects.isNull(group2)) {
                return;
            }
            if (!groupMap.containsKey(group2.getPid())) {
                group1 = classGroupService.findById(group2.getPid());
                if (Objects.nonNull(group1)) {
                    groupMap.put(group1.getId(), group1);
                }
            }
            if (!classMap.containsKey(group2.getClassId())) {
                classResult = classService.findByClassId(group2.getClassId());
                if (Objects.nonNull(classResult)) {
                    classMap.put(classResult.getId(), classResult);
                }
            }
        });
    }


    /**
     * 新奇提醒机器人 -- 身份变更
     *
     * @param classId
     * @param studentId
     * @param studentContent
     * @param teacherContent
     */

    private void sendIdentityChatRemind(Long classId, Long studentId, String studentContent, String teacherContent) {
        List<ChatRemindContentCreateDTO> remindList = new ArrayList<>();
        //新奇提醒机器人 -- 身份变更 -- 被操作人
        remindList.add(new ChatRemindContentCreateDTO(studentId, classId, ChatRemindTypeEnum.IDENTITY_CHANGE, studentContent));
        //新奇提醒机器人 -- 身份变更 -- 助教
        List<ClassStudentResultDTO> assistant = classStudentService.findByClassRole(classId, ClassRoleEnum.ASSISTANT.getCode());
        assistant.forEach(item -> {
            remindList.add(new ChatRemindContentCreateDTO(item.getStudentId(), classId, ChatRemindTypeEnum.IDENTITY_CHANGE, teacherContent));
        });
        //新奇提醒机器人 -- 身份变更 -- 老师
        List<ClassStudentResultDTO> teacher = classStudentService.findByClassRole(classId, ClassRoleEnum.TEACHER.getCode());
        teacher.forEach(item -> {
            remindList.add(new ChatRemindContentCreateDTO(item.getStudentId(), classId, ChatRemindTypeEnum.IDENTITY_CHANGE, teacherContent));
        });
        if (CollectionUtils.isNotEmpty(remindList)) {
            remindContentClient.batchInsert(new ChatRemindContentBatchCreateDTO(remindList));
        }
    }


}
